using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Threading;
using Services;
using SpaceBattle.Logic.SampleLevel;
using System.IO.IsolatedStorage;
using System.IO;
using SpaceBattle.Resources;
using Utilities.Menu.UIElements;

namespace SpaceBattle.Menu
{

    using Game = Microsoft.Xna.Framework.Game;
    using Utilities;

    public class ShipSelectionScreen : Microsoft.Xna.Framework.DrawableGameComponent
    {

        #region New Fields

        #region Constants
        private const float NearPlane = 1.0F;
        private const float FarPlane = 230F;
        private const float LeftBounceMargin = -40;
        private const float RightBounceMargin = 210;
        private const int DistanceBetweenShips = 50;
        private const int NumShips = 6;
        #endregion

        #region Public Fields

        #endregion

        #region Private Fields
        private BattleShip[] Ships;
        private BattleShip _selectedShip = null;
        private int _selectedShipIndex = -1;
        private BasicEffect _shipEffect;
        private ShipStats _shipStats;
        float align_line = -30;

        private Texture2D _nameFadeBG;

        private bool _flicked = false;

        private Rectangle _shipNameBGRect = new Rectangle(0, 150, 300, 50);
        private Color DarkRed = new Color(295, 73, 94, 128);
        #endregion

        #endregion

        SpriteBatch sprite_batch;
        SoundEffect click, error;
        Texture2D confirm_box;
        Button confirm, back, buy;
        GameMode game_mode;
        RenderTarget2D renderTarget;
        float rot, wait_to_tap = 0.5f;

        StateEntry campaign_state;

        public ShipSelectionScreen(Game game, GameMode game_mode)
            : base(game)
        {
            this.game_mode = game_mode;
            campaign_state = Leaderboard.GetCampaignState();

            rot = MathHelper.ToRadians(180);
            available = new bool[campaign_state.Ships.Count];

            for (int i = 0; i < available.Length; i++)
            {
                if (game_mode == GameMode.Campaign)
                    available[campaign_state.Ships[i].Index] = campaign_state.CampaignState.Ships[i].Unlocked == 0 ? false : true;
                else
                    available[campaign_state.Ships[i].Index] = campaign_state.Ships[i].Unlocked == 0 ? false : true;
                if (available[campaign_state.Ships[i].Index])
                    _selectedShipIndex = i;
            }

            ships_stats = (Game.Services.GetService(typeof(ConfigurationService)) as ConfigurationService).Ships;
        }

        ContentManager Content { get { return Game.Content; } }

        ArrayList<ShipDescription> ships_stats;
        InputManager input_manager;
        public override void Initialize()
        {
            input_manager = new InputManager(Game);
            Game.Components.Add(input_manager);
            input_manager.OnTap += new InputManager.Tap(on_tap);
            input_manager.OnFlick += new InputManager.Flick(on_flick);

            base.Initialize();
        }

        #region Tap Handler
        float press_timer;
        void on_tap(Vector2 tap_position)
        {
            if (wait_to_tap <= 0.0f)
            {
                var p = tap_position.ToPoint(screen_transform);

                if (confirm.CollisionBox.Contains(p))
                {
                    if (_selectedShipIndex > -1 && campaign_state.CampaignState.Ships[_selectedShipIndex].Unlocked == 1)
                    {
                        if (OnShipSelected != null)
                        {
                            click.Play(AudioManager.Volume, 0.0f, 0.0f);
                            Leaderboard.SaveCampaignState(campaign_state);
                            OnShipSelected((ShipType)_selectedShipIndex);
                        }
                    }
                    else
                        error.Play(AudioManager.Volume, 0.0f, 0.0f);
                }

                else if (buy.CollisionBox.Contains(p) && campaign_state.CampaignState.Ships[_selectedShipIndex].Unlocked == 0 &&
                    campaign_state.Ships[_selectedShipIndex].Price <= campaign_state.CampaignState.Credits && _selectedShipIndex > 0 && 
                    campaign_state.Ships[_selectedShipIndex - 1].Unlocked == 1)
                {
                    click.Play(AudioManager.Volume, 0.0f, 0.0f);
                    campaign_state.Ships[_selectedShipIndex].Unlocked = 1;
                    campaign_state.CampaignState.Ships[_selectedShipIndex].Unlocked = 1;
                    campaign_state.CampaignState.Credits -= campaign_state.Ships[_selectedShipIndex].Price;
                    available[_selectedShipIndex] = true;
                    Ships[_selectedShipIndex].IsLocked = false;
                }

                else if (back.CollisionBox.Contains(p) || input_manager.IsBackButtonPressed())
                {
                    click.Play(AudioManager.Volume, 0.0f, 0.0f);
                    Leaderboard.SaveCampaignState(campaign_state);

                    if (game_mode == GameMode.Campaign)
                        StateManager.SelectCampaignScreen(Game, null);
                    else
                        StateManager.SelectMenu(Game);
                }

                else
                    error.Play(AudioManager.Volume, 0.0f, 0.0f);
            }
        }
        #endregion

        public delegate void SelectShip(ShipType selected_ship);
        public event SelectShip OnShipSelected;

        Matrix screen_transform;
        Texture2D buy_box;
        SpriteFont font32, text_font, font18, font16;
        Texture2D white_pixel;

        protected override void LoadContent()
        {
            sprite_batch = new SpriteBatch(Game.GraphicsDevice);
            screen_transform = Matrix.CreateScale(GraphicsDevice.Viewport.Width / SpaceBattleGame.DEFAULT_SCR_WIDTH,
                GraphicsDevice.Viewport.Height / SpaceBattleGame.DEFAULT_SCR_HEIGHT, 1.0f);
            confirm_box = game_mode == GameMode.Campaign ? Content.Load<Texture2D>("Menu/button_fwd") : Content.Load<Texture2D>("Menu/button_play_ext");
            back_txt = Content.Load<Texture2D>("Menu/button_rwd");
            buy_box = Content.Load<Texture2D>("Menu/button_cart");
            _nameFadeBG = Content.Load<Texture2D>("Menu/name_fade");
            font32 = Content.Load<SpriteFont>("Fonts/OCRAExtended32");
            font18 = Content.Load<SpriteFont>("Fonts/OCRAExtended18");
            font16 = Content.Load<SpriteFont>("Fonts/OCRAExtended16");
            font14 = Content.Load<SpriteFont>("Fonts/Orator14");
            text_font = Content.Load<SpriteFont>("Fonts/VerySmall");
            white_pixel = Content.Load<Texture2D>(@"UI\WhitePixel");
            click = Game.Content.Load<SoundEffect>("Audio/button");
            error = Game.Content.Load<SoundEffect>("Audio/error");

            _shipStats = new ShipStats(white_pixel, font16);

            confirm = new Button
            {
                Position = new Vector2(GraphicsDevice.Viewport.Width - confirm_box.Width - 10, GraphicsDevice.Viewport.Height / 2.0f - confirm_box.Height / 2.0f),
                Label = "",
                CollisionBox = new Rectangle(GraphicsDevice.Viewport.Width - confirm_box.Width - 20, (int)(GraphicsDevice.Viewport.Height / 2.0f - confirm_box.Height / 2.0f) - 10, confirm_box.Width + 20, confirm_box.Height + 20)
            };

            back = new Button
            {
                Position = new Vector2(10, GraphicsDevice.Viewport.Height / 2.0f - confirm_box.Height / 2.0f),
                Label = "",
                CollisionBox = new Rectangle(0, (int)(GraphicsDevice.Viewport.Height / 2.0f - confirm_box.Height / 2.0f) - 10, confirm_box.Width + 20, confirm_box.Height + 20)
            };

            buy = new Button
            {
                Position = new Vector2(500, 280),
                Label = Strings.Buy,
                CollisionBox = new Rectangle(490, 290, buy_box.Width + 20, buy_box.Height + 20)
            };

            for (int i = 0; i <= (int)WeaponType.Shockwave; i++)
            {
                max_damage += WeaponConfig.GetWeapon(ShipType.PlayerCruiser, (WeaponType)i).Damage * 1.3f;
            }

            #region New Constructor

            _shipEffect = new BasicEffect(GraphicsDevice);

            Ships = new BattleShip[NumShips];
            float x = -DistanceBetweenShips;
            float y = 15;
            float z = -50;
            for (int i = 0; i < Ships.Length; i++)
            {
                Ships[i] = new BattleShip(Game.Content.Load<Model>(ships_stats[i].ModelPath), 
                    Game.Content.Load<Model>(@"Capital Ships\e_sf10"), 
                    campaign_state.Ships[i].Unlocked == 0, x, y, z);
                x += DistanceBetweenShips;
                z -= DistanceBetweenShips;
            }

            _selectedShip = Ships[0];
            _selectedShipIndex = 0;

            #endregion

            base.LoadContent();
        }

        float max_damage = 0.0f;

        protected override void Dispose(bool disposing)
        {
            Game.Services.RemoveService(typeof(IInputManager));

            base.Dispose(disposing);
        }

        public override void Update(GameTime gameTime)
        {
            wait_to_tap -= (float)gameTime.ElapsedGameTime.TotalSeconds;

            #region New Update

            BattleShip _last = Ships[Ships.Length - 1];

            bool bounce = _last.Position.X < LeftBounceMargin || _last.Position.X > RightBounceMargin;

            foreach (BattleShip ship in Ships)
            {
                ship.Update(gameTime, false);
            }

            if ( Math.Abs(BattleShip.GlobalVelocity) < 100 
                || bounce)
            {
                var dist_from_fix = GetVelocityCorrection().X;
                dist_from_fix *= 1+(int)(Math.Abs(dist_from_fix) / 50);

                var vec = MathHelper.Lerp(
                    BattleShip.GlobalVelocity,
                    dist_from_fix,
                    6 * (float)gameTime.ElapsedGameTime.TotalSeconds*
                    Math.Max(0.5f, Math.Min(1, (20 - Math.Abs(dist_from_fix)) / 20)));

                foreach (BattleShip ship in Ships)
                {
                    ship.Velocity = new Vector2(vec);
                }
                //_flicked = false;
            }
            
            if (Math.Abs(BattleShip.GlobalVelocity) < 50)
                _flicked = false;
            
            #region Ship Stats update
            if (_selectedShipIndex != -1)
            {
                var shipStat = ships_stats[_selectedShipIndex];
                var damage = 0.0f;
                for (int j = 0; j < shipStat.PrimaryWeapons.Count; j++) damage += shipStat.PrimaryWeapons[j].Damage;
                for (int j = 0; j < shipStat.SecondaryWeapons.Count; j++) damage += shipStat.SecondaryWeapons[j].Damage;
                damage = damage / max_damage;

                _shipStats.Armor = shipStat.Armor;
                _shipStats.Damage = damage;
                _shipStats.MaxShield = shipStat.MaxShield / ConfigurationService.MaxShield;
                _shipStats.Speed = shipStat.Speed;
                _shipStats.TimeToWarp = shipStat.TimeToWarp;
            }
            else
            {
                _shipStats.Armor = 0;
                _shipStats.Damage = 0;
                _shipStats.MaxShield = 0;
                _shipStats.Speed = 0;
                _shipStats.TimeToWarp = 0;
            }

            #endregion


            #endregion

            base.Update(gameTime);
        }

        private Vector2 GetVelocityCorrection()
        {
            float nearestToZero = Math.Abs(Ships[0].Position.X - align_line);

            int index = 0;

            for (int i = 0; i < Ships.Length; i++)
            {
                var ship = Ships[i];

                var curr = Math.Abs(ship.Position.X - align_line);
                if (curr < nearestToZero)
                {
                    nearestToZero = curr;
                    index = i;
                }
            }

            //prevents index out of bounds. Sometimes happens in async systems :)
            index = index >= Ships.Length ? Ships.Length - 1 : index;

            _selectedShip = Ships[index];
            _selectedShipIndex = index;
            var nearestX = _selectedShip.Position.X;

            //v = (x0 - xt) * friction -> serie geometrica
            //var m = (nearest_x - align_line) * 2.9F; //0.09F * 10 * (50F - nearestToZero) * 1.5F;
#warning funny variables :|
            var m = (align_line - nearestX);

            return new Vector2(m);
        }

        bool[] available;
        private Texture2D stat_bg;
        private SpriteFont font14;
        private Texture2D back_txt;
        public override void Draw(GameTime gameTime)
        {
            GraphicsDevice.BlendState = BlendState.Opaque;

            rot += (float)(gameTime.ElapsedGameTime.TotalSeconds / 2.0f);

            #region Effect Setup
            GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
            GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
            GraphicsDevice.DepthStencilState = DepthStencilState.Default;

            _shipEffect.EnableDefaultLighting();
            _shipEffect.View = Matrix.CreateLookAt(Vector3.Backward, Vector3.Zero, Vector3.Up);
            _shipEffect.Projection = Matrix.CreatePerspectiveFieldOfView(
                                        MathHelper.PiOver2,
                                        Game.GraphicsDevice.Viewport.AspectRatio, NearPlane, FarPlane);
            #endregion

            for (int i = 0; i < Ships.Length; i++)
            {
                var ship = Ships[i];

                GraphicsDevice.BlendState = ship.IsLocked ? BlendState.Additive : BlendState.Opaque;

                ship.View = _shipEffect.View;
                ship.Projection = _shipEffect.Projection;
                ship.Draw(gameTime, i == _selectedShipIndex);
            }

            var title = Strings.SelectShip;
            var title_pos = new Vector2(sprite_batch.GraphicsDevice.Viewport.Width / 2.0f - font32.MeasureString(title).X / 2.0f, 40);

            sprite_batch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, screen_transform);
            
            sprite_batch.DrawString(font32, title, title_pos, Color.White);

            if (game_mode == GameMode.Campaign)
            {
                if (_selectedShipIndex > -1 && campaign_state.CampaignState.Ships[_selectedShipIndex].Unlocked == 0)
                {
                    var cost_vect = new Vector2(230, 425);
                    var cost = Strings.Cost + campaign_state.Ships[_selectedShipIndex].Price;
                    
                    sprite_batch.DrawString(font16, cost, cost_vect, Color.White);

                    var buy_vect = buy.Position;
                    sprite_batch.Draw(buy_box, buy_vect, Color.White *
                        (campaign_state.CampaignState.Credits >= campaign_state.Ships[_selectedShipIndex].Price && 
                        _selectedShipIndex > 0 && campaign_state.Ships[_selectedShipIndex - 1].Unlocked == 1 ? 1.0f : 0.5f));
                    sprite_batch.DrawString(font16, Strings.Buy, new Vector2(buy_vect.X + (buy_box.Width / 2.0f - 
                        font16.MeasureString(Strings.Buy).X / 2.0f), buy_vect.Y + buy_box.Height + 10), Color.White *
                        (campaign_state.CampaignState.Credits >= campaign_state.CampaignState.Ships[_selectedShipIndex].Price ? 1.0f : 0.5f));
                }

                sprite_batch.DrawString(font18, Strings.Credits_l + " " + campaign_state.CampaignState.Credits, new Vector2(602, 442), 
                    Color.Black);
                sprite_batch.DrawString(font18, Strings.Credits_l + " " + campaign_state.CampaignState.Credits, new Vector2(600, 440), 
                    Color.White);
            }

            sprite_batch.Draw(confirm_box, confirm.Position, _selectedShipIndex > -1 &&
            campaign_state.CampaignState.Ships[_selectedShipIndex].Unlocked == 1 ? Color.White : Color.White * 0.5f);
            sprite_batch.Draw(back_txt, back.Position, Color.White);

            #region Draw Stats
            sprite_batch.Draw(_nameFadeBG, _shipNameBGRect, Color.White);
            string name = GetShipName();
            sprite_batch.DrawString(font18, name, new Vector2(20, 160), Color.White);

            _shipStats.Draw(gameTime, sprite_batch);
            #endregion
            sprite_batch.End();

            base.Draw(gameTime);
        }

        private string GetShipName()
        {
            switch (_selectedShipIndex)
            {
                case 0:
                    return "Fighter";
                case 1:
                    return "Corvette";
                case 2:
                    return "Frigate";
                case 3:
                    return "Cruiser";
                case 4:
                    return "Battleship";
                case 5:
                    return "Juggernaut";
                default:
                    return "";
            }
        }

        private void on_flick(Vector2 delta)
        {
            _selectedShipIndex = -1; //reset selection and stats :)
            _flicked = true;
            foreach (BattleShip ship in Ships)
            {
                ship.Velocity = delta*0.09f;
            }
        }

        private List<Texture2D> GetStatTextures()
        {
            var txts = new List<Texture2D>();

            var first_bar_color = new Color(62, 62, 62) * 0.5f;
            var second_bad_color = Color.DarkRed;
            var bar_length = 208;
            var bar_height = 19;
            var y_offset = 65;

            var w = GraphicsDevice.Viewport.Width;
            var h = GraphicsDevice.Viewport.Height;

            var y_text = 375;
            var y = 400;
            var x = w / 2 - bar_length / 2;

            for (int i = 0; i < campaign_state.Ships.Count; i++)
            {
                var ship = ships_stats[i];

                GraphicsDevice.SetRenderTarget(renderTarget);

                GraphicsDevice.Clear(Color.Black * 0.5f);

                sprite_batch.Begin();

                var damage = 0.0f;

                for (int j = 0; j < ships_stats[i].PrimaryWeapons.Count; j++) damage += ships_stats[i].PrimaryWeapons[j].Damage;
                for (int j = 0; j < ships_stats[i].SecondaryWeapons.Count; j++) damage += ships_stats[i].SecondaryWeapons[j].Damage;

                damage = damage / max_damage;

                sprite_batch.DrawString(font16, Strings.Stat_Damage, new Vector2(x, y_text), Color.White);
                sprite_batch.Draw(white_pixel, new Rectangle(x, y, bar_length, bar_height), first_bar_color);
                sprite_batch.Draw(white_pixel, new Rectangle(x, y, (int)(bar_length * damage), bar_height), second_bad_color);

                y += y_offset;
                y_text += y_offset;

                sprite_batch.DrawString(font16, Strings.Stat_Armor, new Vector2(x, y_text), Color.White);
                sprite_batch.Draw(white_pixel, new Rectangle(x, y, bar_length, bar_height), first_bar_color);
                sprite_batch.Draw(white_pixel, new Rectangle(x, y, (int)(bar_length * ship.Armor), bar_height), second_bad_color);

                y += y_offset;
                y_text += y_offset;

                sprite_batch.DrawString(font16, Strings.Stat_Shield, new Vector2(x, y_text), Color.White);
                sprite_batch.Draw(white_pixel, new Rectangle(x, y, bar_length, bar_height), first_bar_color);
                sprite_batch.Draw(white_pixel, new Rectangle(x, y, (int)(bar_length * (ship.MaxShield / ConfigurationService.MaxShield)), bar_height), second_bad_color);

                y += y_offset;
                y_text += y_offset;

                sprite_batch.DrawString(font16, Strings.Stat_Warp, new Vector2(x, y_text), Color.White);
                sprite_batch.Draw(white_pixel, new Rectangle(x, y, bar_length, bar_height), first_bar_color);
                sprite_batch.Draw(white_pixel, new Rectangle(x, y, (int)(bar_length * ship.TimeToWarp), bar_height), second_bad_color);

                y += y_offset;
                y_text += y_offset;

                sprite_batch.DrawString(font16, Strings.Stat_Speed, new Vector2(x, y_text), Color.White);
                sprite_batch.Draw(white_pixel, new Rectangle(x, y, bar_length, bar_height), first_bar_color);
                sprite_batch.Draw(white_pixel, new Rectangle(x, y, (int)(bar_length * ship.Speed), bar_height), second_bad_color);

                sprite_batch.End();

                GraphicsDevice.SetRenderTarget(null);

                txts.Add(renderTarget);
            }

            return txts;
        }
    }

    #region Support Class

    public class ShipStats
    {
        private Color EquipmentBarColor = Color.DarkRed;
        private Color FirstBarColor = new Color(62, 62, 62) * 0.5F;
        private const int BarWidth = 150;
        private const int BarHeight = 15;
        private const int YOffset = 30;
        private const int XOffset = 200;

        public SpriteFont font16 { get; set; }

        #region Config variables
        private float[] StatBars = new float[5];

        private float _damage;
        public float Damage
        {
            get { return _damage; }
            set
            {
                _damage = value;
                StatBars[0] = _damage;
            }
        }

        private float _armor;
        public float Armor
        {
            get { return _armor; }
            set
            {
                _armor = value;
                StatBars[1] = _armor;
            }
        }

        private float _maxShield;
        public float MaxShield
        {
            get { return _maxShield; }
            set
            {
                _maxShield = value;
                StatBars[2] = _maxShield;
            }
        }

        private float _timeToWarp;
        public float TimeToWarp
        {
            get { return _timeToWarp; }
            set
            {
                _timeToWarp = value;
                StatBars[3] = _timeToWarp;
            }
        }

        private float _speed;
        public float Speed
        {
            get { return _speed; }
            set
            {
                _speed = value;
                StatBars[4] = _speed;
            }
        }
        #endregion

        private Texture2D white_pixel;

        public ShipDescription ShipDescription { get; set; }

        private String[] StatTitles = {Strings.Stat_Damage, Strings.Stat_Armor, Strings.Stat_Shield,
                                      Strings.Stat_Warp, Strings.Stat_Speed};


        public ShipStats(Texture2D WhitePixel, SpriteFont Font16)
        {
            this.white_pixel = WhitePixel;
            this.font16 = Font16;
        }

        public void Update(GameTime gameTime)
        {

        }

        public void Draw(GameTime gameTime, SpriteBatch sprite_batch)
        {
            var YStart = 270;
            var y_text = YStart;

            for (int i = 0; i < StatBars.Length; i++)
            {
                StatDraw(sprite_batch, StatTitles[i], ref y_text, ref YStart, (int)(StatBars[i] * BarWidth));

                YStart += YOffset;
                y_text += YOffset;
            }

        }

        private void StatDraw(SpriteBatch sprite_batch, String StatTitle, ref int y_text, ref int y, int bar_length)
        {
            sprite_batch.DrawString(font16, StatTitle, new Vector2(XOffset + BarWidth + 4, y_text), Color.White);
            sprite_batch.Draw(white_pixel, new Rectangle(XOffset, y, BarWidth, BarHeight), FirstBarColor);
            sprite_batch.Draw(white_pixel, new Rectangle(XOffset, y, bar_length, BarHeight), EquipmentBarColor);
        }
    }

    class BattleShip
    {
        #region Constants
        private const float _friction = 0.95F;
        private const float _bounce = .5F;
        #endregion

        private Matrix _world;
        private Matrix _view;
        private Matrix _projection;
        private Model _model, _lockedShipModel;
        private bool _isLocked;

        private Vector2 _velocity;
        private Vector3 _position;

        #region Public Fields
        public Matrix World
        {
            get { return _world; }
            internal set { _world = value; }
        }

        public Matrix View
        {
            get { return _view; }
            set { _view = value; }
        }

        public Matrix Projection
        {
            get { return _projection; }
            set { _projection = value; }
        }

        public Vector3 Position
        {
            get { return _position; }
            set { _position = value; }
        }

        public Vector2 Velocity
        {
            get { return _velocity; }
            set { _velocity = value; }
        }

        public bool IsLocked
        {
            get { return _isLocked; }
            set { _isLocked = value; }
        }

        public static float GlobalVelocity { get; set; }
        #endregion

        public BattleShip(Model model, Model lock_ship, bool isLocked, float StartX, float StartY, float StartZ)
        {
            _model = model;
            _lockedShipModel = lock_ship;
            _isLocked = isLocked;

            _velocity = new Vector2();
            _position = new Vector3(StartX, StartY, StartZ);
            _world = Matrix.Identity;
        }

        public void Update(GameTime gameTime, bool bounce)
        {
            _position += new Vector3(_velocity.X, 0, -_velocity.X) * (float)gameTime.ElapsedGameTime.TotalSeconds;
            _velocity *= _friction;
            //float vel = _velocity.X * 0.09F * (float)gameTime.ElapsedGameTime.TotalSeconds;
            //_position.X += bounce ? -vel : vel;
            //_velocity.X *= bounce ? -_bounce : _friction;

            //_position.Z -= bounce ? -vel : vel;

            GlobalVelocity = _velocity.X;            
        }

        float rot;
        public void Draw(GameTime gameTime, bool rotate)
        {
            var dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
            rot = rotate ? rot + dt : Math.Max(0, rot - dt);

            _world = CreateWorldMatrix(rot);
            if (_isLocked)
                _lockedShipModel.Draw(_world, _view, _projection);
            else
                _model.Draw(_world, _view, _projection);
        }

        private Matrix CreateWorldMatrix(float time)
        {
            return Matrix.CreateScale(12.0f)
                * Matrix.CreateRotationY(MathHelper.ToRadians(180))
                * Matrix.CreateRotationX(MathHelper.ToRadians(45))
                * Matrix.CreateRotationY(time)
                * Matrix.CreateTranslation(_position);
        }
    }

    #endregion
}